`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: University of Maryland, College Park
// Engineer: Aaron Sikorski
// 
// Create Date:    00:37:08 04/05/2011 
// Module Name:    tree 
// Project Name: FIR Filter
// Target Devices: 
// Description: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module tree #(parameter N = 16, parameter M = 16) (
    input [(N*N)-1:0] PP_in ,
    output [2*N+1:0] out_sc,
    output [2*N+1:0] out_ps
    );

	wire [N-1:0] PPi_in [2*N-1:0];
	wire [2*N+3:0] c[2*N-1:0][2*N-1:0];
	wire [2*N+3:0] pps [2*N-1:0][2*N-1:0];
	
	genvar i,j,k,L;
	generate
	
		for (i = 0; i < N ;i=i+1) begin: create_PP_inArray
	
		assign PPi_in[i][N-1:0] = PP_in[((N*i)+(N-1)):(i*(N-1))];   //[i*N:i*N-N]; 
	
	end
	
		for (j=0; j < 2; j=j+1) begin : column_generator  //Generate Columns
		
		
	if(j==0)begin
		for (k=1; k<=M/4; k=k+1) begin : gen_Level0  //Generate Rows Level 0 only 
				Four2Two #(.BitWidth(N+4)) _FT(	 
																																	
												{ {4{PPi_in[0][N-1]}}, PPi_in[4*k-4][N-1:0] } ,
																								
												{ {3{PPi_in[1][N-1]}}, PPi_in[4*k-3][N-1:0],1'b0 } ,
																																			
												{ {2{PPi_in[2][N-1]}}, PPi_in[4*k-2][N-1:0],2'b0 } ,
												
												{ {1{PPi_in[3][N-1]}},{PPi_in[3][N-1:0]},3'b0},
												
												c[0][k][N+3:0],
												
												pps[0][k][N+3:0]); 
						end
						end
		else  begin
		
		
		for (L=1; L<(M/8); L=L+1) begin : gen_LevelS  //Generates Rows across
		if(j != (j-1)) begin
		Four2Two #(.BitWidth(N+((j*4)))) _FT_Levels(	
												//4*5 was 4*L but why not sign extend to MAX every bit
												{{4*2{c[j-1][L-1][(N+3)+4*L]}}, c[j-1][2*L-1][(N+3)+4*L:0]},
												
												{{4*2{pps[j-1][L-1][(N+3)+4*L]}},pps[j-1][2*L-1][(N+3)+4*L:0]},
												
												{c[j-1][L][(N+3)+4*L:0],{4*2{1'b0}}},
												
												{pps[j-1][L][(N+3)+4*L:0],{4*2{1'b0}}},
												
												//OUTPUT
												c[j][L+1][((N+3)+(4*L)):0],
												pps[j][(L+1)][((N+3)+(4*L)):0]
												
												); 
												end
												
												else begin //We are in the generation of the FINAL CSA just copy above two
																//sign extend and should work
																//
												
												end
												
//Right now works upto 2nd stage going into the final 
// need to figure out a way to limit the FOR loops to go from 
	
	end
	end
	end
	 endgenerate
	 
	 assign out_ps = c[1][2];
	 assign out_sc = pps[1][2];
endmodule
